/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[欢迎加盟知启蒙，一起邂逅框架梦]
 * 
 * https://www.zhiqim.com/gitcan/zhiqim/zhiqim_account.htm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.zhiqim.account.action.pay;

import org.zhiqim.account.ZacConstants;
import org.zhiqim.account.api.pay.WxpayServer;
import org.zhiqim.account.dbo.user.UserTradeWxpay;
import org.zhiqim.account.paycallback.PayCallback;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.context.core.Action;
import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.extend.HashMapSS;
import org.zhiqim.kernel.extend.MapSS;
import org.zhiqim.kernel.extend.TreeMapSS;
import org.zhiqim.kernel.json.Jsons;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Ints;
import org.zhiqim.kernel.util.Longs;
import org.zhiqim.kernel.util.Sqls;
import org.zhiqim.kernel.xml.Xmls;
import org.zhiqim.orm.ZTable;
import org.zhiqim.orm.dbo.Updater;

/**
 * 微信支付通知
 * https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8
 *
 * @version v1.0.0 @author zzy 2018-4-16 新建与整理
 */
public class WxpayNotifyAction implements Action, ZacConstants
{
    private static final Log log = LogFactory.getLog(WxpayNotifyAction.class);
    
    @Override
    public void execute(HttpRequest request) throws Exception
    {
        //第一步，从内容中取出参数，转为MAP对象
        String xml = request.getInputStreamString();
        TreeMapSS map = Xmls.toObject(xml, TreeMapSS.class);
        String returnCode = map.get("return_code");
        if (!WXPAY_SUCCESS.equals(returnCode))
        {
            log.error("收到微信支付通知，服务端验证失败["+returnCode+"]["+map.get("return_msg")+"]");
            return;
        }
        
        long tradeId = Longs.toLong(map.get("out_trade_no"));
        String tradeNo = map.get("transaction_id");
        String resultCode = map.get("result_code");
        
        //第二步，验证签名
        WxpayServer server = Global.getService(WxpayServer.class);
        if (!server.chkSignature(map))
        {
            log.error("收到微信支付通知，签名验证失败["+tradeId+"]["+tradeNo+"]["+resultCode+"]");
            return;
        }
        
        //第三步，从支付宝交易表中取出交易详情
        UserTradeWxpay wxpay = Global.get(ZTable.class).item(UserTradeWxpay.class, tradeId);
        if (wxpay == null)
        {
            log.info("收到微信支付通知["+tradeId+"]["+tradeNo+"]["+resultCode+"]交易不存在");
            return;
        }
        
        //第四步，更新微信支付表，共五项，四项基本数据+验证金额不一致显示ERROR_TOTALFEE
        Updater updater = new Updater();
        updater.addMust("tradeId", tradeId);
        updater.addField("tradeNo", tradeNo);
        updater.addField("tradeNotified", Sqls.nowTimestamp());
        updater.addField("tradeNotifyDesc", Jsons.toString(map));
        
        if (wxpay.getTradeAmount() != Ints.toInt(map.get("total_fee")))
            updater.addField("tradeStatus", TRADE_EAMOUNT);
        else
            updater.addField("tradeStatus", WXPAY_SUCCESS.equals(resultCode)?TRADE_SUCCESS:TRADE_FAILURE);
        Global.get(ZTable.class).update(UserTradeWxpay.class, updater);
        
        if (!WXPAY_SUCCESS.equals(resultCode))
        {//业务结果不成功的不回消息
            log.info("收到微信支付通知["+tradeId+"]["+tradeNo+"]["+resultCode+"]交易失败，不回消息");
            return;
        }
        
        //第五步，查询内部订单，已处理的不再处理
        wxpay.setTradeNo(tradeNo);
        wxpay.setTradeStatus(TRADE_SUCCESS);
        wxpay.setTradeNotifyDesc(Jsons.toString(map));
        
        String callback = wxpay.getTradeCallback();

        Object obj = Global.getCreate(Global.getClass(callback));
        PayCallback call = (PayCallback)obj;
        call.call(wxpay);
        
        //第六步，响应微信端成功
        MapSS returnMap = new HashMapSS();
        returnMap.setXmlTag("xml");
        returnMap.put("return_code", "SUCCESS");
        returnMap.put("return_msg", "OK");
        String returnXml = Xmls.toString(returnMap);
        request.getResponse().print(returnXml);
    }
}
